<?php

define('API_CURL_UPLOAD_FILE','__file');  

#支持的请求方法  
define('REQUEST_METHOD_GET','GET');  
define('REQUEST_METHOD_POST','POST');  
define('REQUEST_METHOD_HEAD','HEAD');  
  
#请求行为  
define('REQUEST_BEHAVIOR_ALLOW_REDIRECT','allow_redirect');  
define('REQUEST_BEHAVIOR_MAX_REDIRECT','max_redirect');  
define('REQUEST_BEHAVIOR_USER_AGENT','user_agent');  
define('REQUEST_BEHAVIOR_AUTOREFERER','autoreferer');  
define('REQUEST_BEHAVIOR_UPLOAD','upload');  
define('REQUEST_BEHAVIOR_CONNECTTIMEOUT','connecttimeout');  
define('REQUEST_BEHAVIOR_DNS_CACHE_TIMEOUT','dns_cache_timeout');  
define('REQUEST_BEHAVIOR_TIMEOUT','timeout');  
define('REQUEST_BEHAVIOR_ENCODING','encoding');  
define('REQUEST_BEHAVIOR_ERROR_HANDLER','error_handler');  
define('REQUEST_BEHAVIORS','behaviors');  
$GLOBALS[REQUEST_BEHAVIORS] = array(
    REQUEST_BEHAVIOR_ALLOW_REDIRECT             => TRUE,   
    REQUEST_BEHAVIOR_MAX_REDIRECT               => 5,   
    REQUEST_BEHAVIOR_USER_AGENT                 => 'curl-lib',   
    REQUEST_BEHAVIOR_AUTOREFERER                => TRUE,   
    REQUEST_BEHAVIOR_UPLOAD                     => FALSE,   
    REQUEST_BEHAVIOR_CONNECTTIMEOUT             => 3,   
    REQUEST_BEHAVIOR_DNS_CACHE_TIMEOUT          => 3600,   
    REQUEST_BEHAVIOR_TIMEOUT                    => 3,   
    REQUEST_BEHAVIOR_ENCODING                   => 'gzip',   
    REQUEST_BEHAVIOR_ERROR_HANDLER              => '__default_curl_error_handler',   
);  
  
define('MULTIPART_FORM_DATA_HEAD_FMT',              'Content-Type: multipart/form-data; boundary=----------------------------%s');  
define('MULTIPART_FORM_DATA_BODY_STRING',           "------------------------------%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n");  
define('MULTIPART_FORM_DATA_BODY_FILE',             "------------------------------%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: application/octet-stream\r\n\r\n%s\r\n");  
define('MULTIPART_FORM_DATA_BODY_END',              "------------------------------%s--\r\n\r\n");  
  
#响应键值  
define('RESP_CODE',                                 'resp_code');  
define('RESP_BODY',                                 'resp_body');  
define('RESP_HEADER',                               'resp_header');  
  
#HTTP 1xx状态验证  
define('HTTP_1XX_RESP',                             '/^HTTP\/1.[01] 1\d{2} \w+/');  
  
#默认错误处理的错误消息  
define('E_CURL_ERROR_FMT',                              'curl "%s" error[%d]: %s');

class curl {
	#默认的curl错误处理
	static function __default_curl_error_handler($curl, $url, $errno, $errstr) {
		trigger_error(sprintf(E_CURL_ERROR_FMT, $url, $errno, $errstr), E_USER_ERROR);
	}
	
	#切换CURL请求方法
	static function __method_switch($curl, $method) {
		switch ( $method) {
		case REQUEST_METHOD_POST:
			self::__curl_setopt($curl, CURLOPT_POST, TRUE);
		break;
		case REQUEST_METHOD_HEAD:
			self::__curl_setopt($curl, CURLOPT_NOBODY, TRUE);
		break;
		case REQUEST_METHOD_GET:
			self::__curl_setopt($curl, CURLOPT_HTTPGET, TRUE);
		break;
		default:
		break;
		}
	}
	
	#设置默认头信息
	static function __default_header_set($curl) {
		self::__curl_setopt($curl, CURLOPT_RETURNTRANSFER,            TRUE);
		self::__curl_setopt($curl, CURLOPT_HEADER,                    TRUE);
		self::__curl_setopt($curl, CURLOPT_FOLLOWLOCATION,            (bool)self::curl_behavior(REQUEST_BEHAVIOR_ALLOW_REDIRECT));
		self::__curl_setopt($curl, CURLOPT_MAXREDIRS,                 (int)self::curl_behavior(REQUEST_BEHAVIOR_MAX_REDIRECT));
		self::__curl_setopt($curl, CURLOPT_USERAGENT,                 (string)self::curl_behavior(REQUEST_BEHAVIOR_USER_AGENT));
		self::__curl_setopt($curl, CURLOPT_AUTOREFERER,               (bool)self::curl_behavior(REQUEST_BEHAVIOR_AUTOREFERER));
		self::__curl_setopt($curl, CURLOPT_UPLOAD,                    (bool)self::curl_behavior(REQUEST_BEHAVIOR_UPLOAD));
		self::__curl_setopt($curl, CURLOPT_CONNECTTIMEOUT,            (int)self::curl_behavior(REQUEST_BEHAVIOR_CONNECTTIMEOUT));
		self::__curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT,         (int)self::curl_behavior(REQUEST_BEHAVIOR_DNS_CACHE_TIMEOUT));
		self::__curl_setopt($curl, CURLOPT_TIMEOUT,                   (int)self::curl_behavior(REQUEST_BEHAVIOR_TIMEOUT));
		self::__curl_setopt($curl, CURLOPT_ENCODING,                  (string)self::curl_behavior(REQUEST_BEHAVIOR_ENCODING));
	}
	
	#设置用户自定义头信息
	static function __custom_header_set($curl, $headers = NULL) {
		if ( empty($headers) ) return ;
		if (is_string($headers)){
		$headers    = explode("\r\n", $headers);
			#类型修复
			foreach ($headers as &$header){
				if (is_array($header)){
					$header = sprintf('%s: %s', $header[0], $header[1]);
					self::__curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
				}
			}
		}
	}

	#设置请求body
	static function __datas_set($curl, $datas = NULL) {
		if (empty($datas)) return ;
		if (is_array($datas)) {
			$custom_body        = FALSE;
			$uniqid             = uniqid();
			$custom_body_str    = '';
			foreach ( $datas as $name => $data ) {
				if (is_array($data) && array_key_exists(API_CURL_UPLOAD_FILE, $data)) {
					$file   = $data[API_CURL_UPLOAD_FILE];
					if ( file_exists($file) ) {
						$custom_body        = TRUE;
						$custom_body_str    .= sprintf(MULTIPART_FORM_DATA_BODY_FILE,
						$uniqid, $name,
						$file, file_get_contents($file));
					}
				} else {
					$custom_body_str        .= sprintf(MULTIPART_FORM_DATA_BODY_STRING,
					$uniqid, $name, $data);
				}
			}
			if ($custom_body) {
				self::__curl_setopt($curl, CURLOPT_HTTPHEADER, array(sprintf(MULTIPART_FORM_DATA_HEAD_FMT, $uniqid)));
				$datas = $custom_body_str . sprintf(MULTIPART_FORM_DATA_BODY_END, $uniqid);
			}
		}
			self::__curl_setopt($curl, CURLOPT_POSTFIELDS, $datas);
		}
		
	#对curl_setopt的封装
	static function __curl_setopt($curl, $optname, $optval) {
		curl_setopt($curl, $optname, $optval);
		self::__curl_error($curl);
	}
		
	#curl错误检查处理
	static function __curl_error($curl) {
		if (curl_errno($curl)) {
			$url    = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
			$errno  = curl_errno($curl);
			$errstr = curl_error($curl);
			$errh   = self::curl_behavior(REQUEST_BEHAVIOR_ERROR_HANDLER);
		if (function_exists($errh))
			$errh($curl, $url, $errno, $errstr);
		}
	}
	
	#api默认行为切换
	static function curl_behavior($names, $values = NULL) {
		if (!is_string($names) && !is_array($names)) return ;
		if (!is_null($values)) {
			if (is_string($names)){
				$GLOBALS[REQUEST_BEHAVIORS][$names] = $values;
			}else if (is_array($names) && !is_array($values)){
				foreach ($names as $name){
					$GLOBALS[REQUEST_BEHAVIORS][$name]  = $values;
				}
			}else if ( is_array($names) && is_array($values)){
				foreach ($names as $k => $name){
					$GLOBALS[REQUEST_BEHAVIORS][$name]  = $values[$k];
				}
				if (is_string($names)) {
					$return = $GLOBALS[REQUEST_BEHAVIORS][$names];
				} else if (is_array($names)) {
					$return = array();
					foreach ($names as $name){
						$return[$name]  = array_key_exists($name, $GLOBALS[REQUEST_BEHAVIORS]) ? $GLOBALS[REQUEST_BEHAVIORS][$name] : NULL;
					}
					return $return;
				}
			}
		}
	}
	#请求入口
	static function curl_request($url, $method, $datas = NULL, $headers = NULL) {
		$curl = curl_init($url);
		self::__method_switch($curl, $method);
		self::__default_header_set($curl);
		self::__custom_header_set($curl, $headers);
		self::__datas_set($curl, $datas);
		$response   = curl_exec($curl);
		self::__curl_error($curl);
		$status_code    = curl_getinfo($curl, CURLINFO_HTTP_CODE);
		$components     = explode("\r\n\r\n", $response);
		$i              = -1;
		while ( ++ $i < count($components))
		if ( !preg_match(HTTP_1XX_RESP, $components[$i]) ) break;
		$headers        = $components[$i];
		$body           = implode("\r\n\r\n", array_slice($components, $i + 1));
		return array(
				RESP_CODE   => $status_code,
				RESP_HEADER => $headers,
				RESP_BODY   => $body,
		);
	}
	
	#GET请求
	private function curl_get($url, $headers = NULL) {
		return self::curl_request($url, REQUEST_METHOD_GET, NULL, $headers);
	}
	
	#POST请求
	static function curl_post($url, $datas = NULL, $headers = NULL) {
		return  self::curl_request($url, REQUEST_METHOD_POST, $datas, $headers);
	}
	
	#HEAD请求
	private function curl_head($url, $headers = NULL) {
		return  self::curl_request($url, REQUEST_METHOD_HEAD, NULL, $headers);
	}
	
	#构造上传文件字段
	private function curl_post_file($file) {
		return array(
				API_CURL_UPLOAD_FILE    => $file,
		);
	}
	
	#读取响应码
	static function curl_resp_code($resp) {
		return $resp[RESP_CODE];
	}
	
	#读取响应头
	static function curl_resp_header($resp) {
		return $resp[RESP_HEADER];
	}
	
	#读取响应体
	static function curl_resp_body($resp) {
		return $resp[RESP_BODY];
	}
	
}

?>